﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PlanetSim.ParticleSimulator
{
    public struct Vector
    {
        public static Vector Zero = new Vector(0, 0);

        public float X, Y;

        public Vector(float x, float y)
        {
            this.X = x;
            this.Y = y;
        }

        public float Length()
        {
            return Vector.Distance(Vector.Zero, this);
        }

        #region STATIC METHODS

        /// <summary>
        /// Linear interpretation between two vectors.
        /// </summary>
        /// <param name="a">The start vector</param>
        /// <param name="b">The end vector</param>
        /// <param name="t">The parameter variable between 0.0f and 1.0f</param>
        /// <returns></returns>
        public static Vector Lerp(Vector a, Vector b, float t)
        {
            return ((b - a) * t) + a;
        }

        /// <summary>
        /// Returns the Euclidian distance squared between two vectors. 
        /// Useful for optimization in cases where the exact distance is not needed, 
        /// since it does not require an expensive square root operation
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns>The distance squared</returns>
        public static float DistanceSquared(Vector a, Vector b)
        {
            return (float)(Math.Pow(a.X - b.X, 2) + Math.Pow(a.Y - b.Y, 2));
        }

        /// <summary>
        /// Calculates the Euclidian distance between two vectors.
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns>The distance</returns>
        public static float Distance(Vector a, Vector b)
        {
            return (float)Math.Sqrt(Math.Pow(a.X - b.X, 2) + Math.Pow(a.Y - b.Y, 2));
        }

        #endregion

        #region OPERATORS

        public static Vector operator +(Vector a, Vector b)
        {
            return new Vector(a.X + b.X, a.Y + b.Y);
        }

        public static Vector operator -(Vector a, Vector b)
        {
            return new Vector(a.X - b.X, a.Y - b.Y);
        }

        public static Vector operator *(Vector v, float f)
        {
            return new Vector(v.X * f, v.Y * f);
        }

        public static Vector operator *(float f, Vector v)
        {
            return v * f;
        }

        public static Vector operator /(Vector v, float f)
        {
            return new Vector(v.X / f, v.Y / f);
        }

        public static Vector operator -(Vector v)
        {
            return new Vector(-v.X, -v.Y);
        }

        #endregion
    }
}
